package com.woniuxy.security.util;

import cn.hutool.core.io.FileUtil;

import java.io.File;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * Date: 2021/6/29:20:05  <br/>
 * Description:根据RSA算法，生成公钥、私钥；获取公钥、私钥的工具类
 */
public class RsaUtil {
    public static final String RSA = "RSA";

    /**
     * 生成秘钥文件
     * @param pubPath 公钥文件路径
     * @param priPath 私钥文件路径
     * @throws NoSuchAlgorithmException 签名算法异常
     */
    public static void generateKey(String pubPath,String priPath) {
        try {

            //创建秘钥生成器对象
            KeyPairGenerator generator = KeyPairGenerator.getInstance(RSA);
            //生成秘钥的随机数
            SecureRandom random = new SecureRandom();
            //初始化秘钥生成器对象,指定秘钥的长度及随机源
            generator.initialize(2048, random);
            //创建秘钥对对象
            KeyPair keyPair = generator.generateKeyPair();
            //获取公钥
            PublicKey pubKey = keyPair.getPublic();
            //获取私钥
            PrivateKey priKey = keyPair.getPrivate();
            //写入文件
            writeFile(pubPath,pubKey.getEncoded());
            writeFile(priPath,priKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("生成秘钥文件，签名算法异常",e);
        } catch (IOException e) {
            throw new RuntimeException("生成秘钥文件，文件写入异常",e);
        }
    }

    /**
     * 写入文件
     * @param filePath 文件路径
     * @param bytes 字节数组
     * @throws IOException 文件写入异常
     */
    public static void writeFile(String filePath,byte[] bytes) throws IOException {
        File file = new File(filePath);
        String path = filePath.substring(0,filePath.lastIndexOf("/"));
        File pathFile = new File(path);
        if(!pathFile.exists()){
            pathFile.mkdirs();
        }
        if(!file.exists()) {
            // 判断文件或目录是否存在，如果不存在则创建
            file.createNewFile();
        }
        FileUtil.writeBytes(bytes,filePath);
    }

    /**
     * 获取私钥
     * @return
     */
    public static PrivateKey getPrivateKey(String filePath) {
        try {

            byte[] bytes = FileUtil.readBytes(filePath);
            //私钥的编码
            PKCS8EncodedKeySpec encoder = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            return keyFactory.generatePrivate(encoder);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("获取私钥，签名算法异常:",e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("获取私钥，验证私钥异常:",e);
        }
    }

    /**
     * 获取公钥
     * @return
     */
    public static PublicKey getPublicKey(String filePath) {
        try {
            //读取公钥文件
            byte[] bytes = FileUtil.readBytes(new File(filePath));
            //公钥编码
            X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance(RSA);
            return factory.generatePublic(encodedKeySpec);

        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("获取公钥，公钥验证异常：",e);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("签名算法异常：",e);
        }
    }
}
